import { ethers } from 'ethers';
import { CONTRACT_ADDRESS, CONTRACT_ABI } from '../config/contract';

class Web3Service {
  constructor() {
    this.provider = null;
    this.signer = null;
    this.contract = null;
    this.account = null;
  }

  // 连接钱包
  async connectWallet() {
    try {
      if (!window.ethereum) {
        throw new Error('请安装 MetaMask 钱包!');
      }

      // 请求账户访问
      const accounts = await window.ethereum.request({
        method: 'eth_requestAccounts'
      });

      // 创建 provider 和 signer
      this.provider = new ethers.providers.Web3Provider(window.ethereum);
      this.signer = this.provider.getSigner();
      this.account = accounts[0];

      // 创建合约实例
      this.contract = new ethers.Contract(
        CONTRACT_ADDRESS,
        CONTRACT_ABI,
        this.signer
      );

      // 监听账户变化
      window.ethereum.on('accountsChanged', (accounts) => {
        if (accounts.length === 0) {
          this.disconnect();
        } else {
          this.account = accounts[0];
          window.location.reload();
        }
      });

      // 监听网络变化
      window.ethereum.on('chainChanged', () => {
        window.location.reload();
      });

      return this.account;
    } catch (error) {
      console.error('连接钱包失败:', error);
      throw error;
    }
  }

  // 断开连接
  disconnect() {
    this.provider = null;
    this.signer = null;
    this.contract = null;
    this.account = null;
  }

  // 获取当前账户
  getAccount() {
    return this.account;
  }

  // 获取账户余额
  async getBalance(address) {
    if (!this.provider) throw new Error('请先连接钱包');
    const balance = await this.provider.getBalance(address);
    return ethers.utils.formatEther(balance);
  }

  // 铸造 NFT
  async mintNFT(tokenURI, royaltyPercent = 5) {
    if (!this.contract) throw new Error('请先连接钱包');
    try {
      const tx = await this.contract.mint(this.account, tokenURI, royaltyPercent);
      const receipt = await tx.wait();
      
      // 从事件中获取 tokenId
      const event = receipt.events.find(e => e.event === 'NFTMinted');
      const tokenId = event.args.tokenId.toString();
      
      return { tokenId, transactionHash: receipt.transactionHash };
    } catch (error) {
      console.error('铸造 NFT 失败:', error);
      throw error;
    }
  }

  // 获取我的 NFTs
  async getMyNFTs() {
    if (!this.contract) throw new Error('请先连接钱包');
    try {
      const tokenIds = await this.contract.tokensOfOwner(this.account);
      const nfts = [];

      for (let tokenId of tokenIds) {
        const tokenURI = await this.contract.tokenURI(tokenId);
        const owner = await this.contract.ownerOf(tokenId);
        
        // 获取挂单信息
        const listing = await this.contract.listings(tokenId);
        
        nfts.push({
          tokenId: tokenId.toString(),
          tokenURI,
          owner,
          isListed: listing.isActive,
          price: listing.isActive ? ethers.utils.formatEther(listing.price) : null
        });
      }

      return nfts;
    } catch (error) {
      console.error('获取 NFT 列表失败:', error);
      throw error;
    }
  }

  // 获取市场上所有挂单的 NFTs
  async getMarketNFTs() {
    if (!this.contract) throw new Error('请先连接钱包');
    try {
      const activeListings = await this.contract.getActiveListings();
      const nfts = [];

      for (let tokenId of activeListings) {
        const tokenURI = await this.contract.tokenURI(tokenId);
        const owner = await this.contract.ownerOf(tokenId);
        const listing = await this.contract.listings(tokenId);

        nfts.push({
          tokenId: tokenId.toString(),
          tokenURI,
          owner,
          seller: listing.seller,
          price: ethers.utils.formatEther(listing.price),
          isActive: listing.isActive
        });
      }

      return nfts;
    } catch (error) {
      console.error('获取市场 NFT 列表失败:', error);
      throw error;
    }
  }

  // 挂单 NFT
  async listNFT(tokenId, priceInEther) {
    if (!this.contract) throw new Error('请先连接钱包');
    try {
      const price = ethers.utils.parseEther(priceInEther.toString());
      const tx = await this.contract.listNFT(tokenId, price);
      await tx.wait();
      return tx.hash;
    } catch (error) {
      console.error('挂单失败:', error);
      throw error;
    }
  }

  // 取消挂单
  async unlistNFT(tokenId) {
    if (!this.contract) throw new Error('请先连接钱包');
    try {
      const tx = await this.contract.unlistNFT(tokenId);
      await tx.wait();
      return tx.hash;
    } catch (error) {
      console.error('取消挂单失败:', error);
      throw error;
    }
  }

  // 购买 NFT
  async buyNFT(tokenId, priceInEther) {
    if (!this.contract) throw new Error('请先连接钱包');
    try {
      const price = ethers.utils.parseEther(priceInEther.toString());
      const tx = await this.contract.buyNFT(tokenId, { value: price });
      await tx.wait();
      return tx.hash;
    } catch (error) {
      console.error('购买失败:', error);
      throw error;
    }
  }

  // 销毁 NFT
  async burnNFT(tokenId) {
    if (!this.contract) throw new Error('请先连接钱包');
    try {
      const tx = await this.contract.burn(tokenId);
      await tx.wait();
      return tx.hash;
    } catch (error) {
      console.error('销毁失败:', error);
      throw error;
    }
  }

  // 获取 NFT 总供应量
  async getTotalSupply() {
    if (!this.contract) throw new Error('请先连接钱包');
    try {
      const supply = await this.contract.totalSupply();
      return supply.toString();
    } catch (error) {
      console.error('获取总供应量失败:', error);
      throw error;
    }
  }

  // 更新挂单价格
  async updateListingPrice(tokenId, newPriceInEther) {
    if (!this.contract) throw new Error('请先连接钱包');
    try {
      const price = ethers.utils.parseEther(newPriceInEther.toString());
      const tx = await this.contract.updateListingPrice(tokenId, price);
      await tx.wait();
      return tx.hash;
    } catch (error) {
      console.error('更新价格失败:', error);
      throw error;
    }
  }
}

export default new Web3Service();

